﻿using System;
using System.Collections.Generic;
using System.Threading;
using SimpleServiceBus.Bus;
using SimpleServiceBus.Bus.Transport;
using SimpleServiceBus.Endpoint;

namespace SimpleServiceBus.Tests.Stubs
{
    public class TestTransport : BaseTransport
    {
        private readonly object _queueLock = new object();
        public AutoResetEvent NextMessage = new AutoResetEvent(false);
        public Queue<MessageEnvelope> ToReceive = new Queue<MessageEnvelope>();
        private EndpointServiceManager _serviceManager;

        public bool StartWorkerThreads { get; set; }

        public List<SentMessage> SentMessages { get; set; }

        public override string ReturnAddress
        {
            get { return "Test"; }
        }

        public override EndpointServiceManager ServiceManager
        {
            get
            {
                if (_serviceManager != null)
                    return _serviceManager;
                if (Endpoint != null)
                    return Endpoint.LocalServices;
                return base.ServiceManager;
            }
        }

        public int LivingWorkerThreads { get { return _workerThreads.Count; } }

        public void ReplaceServiceManager(EndpointServiceManager serviceManager)
        {
            _serviceManager = serviceManager;
        }

        public void Receive(MessageEnvelope message)
        {
            lock (_queueLock)
                ToReceive.Enqueue(message);
        }

        public void Start(bool startWorkerThreads)
        {
            StartWorkerThreads = startWorkerThreads;
            Start();
        }

        protected override void StartService()
        {
            if (StartWorkerThreads)
                base.StartService();
        }

        protected override void Receive()
        {
            lock (_queueLock)
                if (ToReceive.Count < 1)
                    return;

            base.Receive();
            NextMessage.Set();
        }

        protected override MessageEnvelope GetNextMessage()
        {
            lock (_queueLock)
            {
                if (ToReceive.Count > 0)
                    return ToReceive.Dequeue();
            }
            return null;
        }

        public override int GetNumberOfPendingMessages()
        {
            lock (_queueLock)
                return ToReceive.Count;
        }

        public override void Send(MessageEnvelope m, string[] destination)
        {
            if (String.IsNullOrEmpty(m.MessageID))
                m.MessageID = Guid.NewGuid().ToString();

            if (SentMessages == null)
                SentMessages = new List<SentMessage>();
            SentMessages.Add(new SentMessage {Message = m, Recipients = destination});

            foreach (string address in destination)
            {
                if (address == ReturnAddress)
                {
                    Receive(m);
                    break;
                }
            }
        }

        #region Nested type: SentMessage

        public class SentMessage
        {
            public MessageEnvelope Message { get; set; }
            public string[] Recipients { get; set; }
        }

        #endregion
    }
}